<template>
  <div>
    <div>
      datasss:

      <el-button type="primary">Primary</el-button>
      <el-switch v-model="value1" />
    </div>
    <div id="container" style="height: 100%; width: 100%"></div>
    <task-detail
      ref="taskDetailRef"
      :id="nowTaskId"
      :is-template="'path-template'.indexOf('template') > -1"
      @on-close="refreshTaskList"
    ></task-detail>

    <create-task
      :is-template="'path-template'.indexOf('template') > -1"
      :from-task="fromTask"
      ref="createTaskRef"
      @confirm-click="refreshTaskList"
    ></create-task>
  </div>
</template>

<script setup lang="ts">
import G6 from "@antv/g6";
import processG6 from "../utils/processG6";
import type { INode, IEdge, G6GraphEvent } from "@antv/g6";
import { onMounted, ref, nextTick } from "vue";
import { useRouter } from "vue-router";
import { taskFlowView } from "~/api/task-flow-view.ts";
import { taskRelyList } from "~/api/task-rely-list.ts";
import createTask from "./create-task.vue";
import taskDetail from "./task-detail.vue";
import { _getImg, _msgBoxFun } from "../utils/utils";
const _processG6 = new processG6();
const fromTask = ref();
const currentTargetNode = ref();
const createTaskRef = ref();
const value1 = ref();

const { path, params } = useRouter().currentRoute.value.query || {
  path: "xxx",
};

let graph: any = null;

function setCurrentTargetNode(node: INode | undefined): void {
  currentTargetNode.value = node;
}

// 视图数据
const viewerData: any = ref({
  nodes: [],
  edges: [],
});
const isLoading = ref(false); // 是否加载
const nowTaskId = ref(""); // 当前任务id
const taskDetailRef = ref(); // 任务详情

G6.registerNode(
  "task-node",
  {
    draw: (cfg: any, group: any) => {
      return _processG6.createTaskNode(cfg, group);
    },
    afterDraw: (cfg: any, group: any) => {
      _processG6.afterDraw(cfg, group);
    },
    setState: (name: any, value: any, item: any) => {
      _processG6.setState(name, value, item);
    },
  },
  "rect"
);

G6.registerEdge("task-edge", {
  afterDraw: (cfg: any, group: any) => {
    _processG6.edgeAfterDraw(cfg, group);
  },
  draw: (cfg: any, group: any) => {
    return _processG6.edgeDraw(cfg, group);
  },
  setState: (name: any, value: any, item: any) => {
    _processG6.edgeSetState(name, value, item);
  },
});

G6.registerBehavior("drag-edge", {
  getEvents() {
    return {
      "edge:click": "onEdgeClick",
      "node:mouseup": "onNodeMouseUp",
      dragenter: "onDragEnter",
    };
  },
  onEdgeClick: async (ev: G6GraphEvent) => {
    const target = ev.target;
    const edge = ev.item as IEdge;
    if (
      target.cfg.name == "remove-edge-image1" ||
      target.cfg.name == "remove-edge-image2"
    ) {
      await apiRemoveTaskRely((edge._cfg && edge._cfg.id) || "");
      viewer.value.removeItem(edge);
      refreshTaskList();
    }
  },
  onNodeMouseUp: async (ev: G6GraphEvent) => {
    const node = ev.item;
    // const { x, y, width, height } = _pageCtrl.currentTargetNode?.getBBox() || { x: 0, y: 0, width: 0, height: 0 }
    // console.log(x, y, width, height, ev.x, ev.y)
    if (currentTargetNode.value) {
      const group = currentTargetNode.value.get("group");
      if (group.getShape(ev.x, ev.y)) {
        // console.log(node, 'node', _pageCtrl.currentTargetNode)
        const model1 = node.getModel();
        const model2 = currentTargetNode.value.getModel();
        console.log(model1.id, model2.id, "model2.id");
        // if (_pageCtrl.detail.value.tableStatus == 3 || (!_pageCtrl.isTemplate.value && !_pageCtrl.isManager)) {
        //   return
        // }
        if (model1.id != model2.id) {
          viewer.value.addItem("edge", {
            source: model1.id,
            target: model2.id,
          });
          try {
            await setRelyTask(model1.id || "", model2.id + "");
          } catch {
            //
          }
          refreshTaskList();
        }
      }
    }
  },
  onDragEnter: async (ev: G6GraphEvent) => {
    const node = ev.item;
    const type = node.getType();
    if (type == "node") {
      setCurrentTargetNode(node as INode);
    }
  },
});
console.log("taskFlowView", taskFlowView);
console.log("taskRelyList", taskRelyList);

const ICON_MAP = {
  a: "https://gw.alipayobjects.com/mdn/rms_8fd2eb/afts/img/A*0HC-SawWYUoAAAAAAAAAAABkARQnAQ",
  b: "https://gw.alipayobjects.com/mdn/rms_8fd2eb/afts/img/A*sxK0RJ1UhNkAAAAAAAAAAABkARQnAQ",
};

G6.registerNode(
  "card-node",
  {
    drawShape: function drawShape(cfg, group) {
      const r = 2;
      const shape = group.addShape("rect", {
        attrs: {
          x: 0,
          y: 0,
          width: 200,
          height: 60,
          stroke: cfg.color,
          radius: r,
        },
        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
        name: "main-box",
        draggable: true,
      });

      group.addShape("rect", {
        attrs: {
          x: 0,
          y: 0,
          width: 200,
          height: 20,
          fill: cfg.color,
          radius: [r, r, 0, 0],
        },
        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
        name: "title-box",
        draggable: true,
      });

      // left icon
      group.addShape("image", {
        attrs: {
          x: 4,
          y: 2,
          height: 16,
          width: 16,
          cursor: "pointer",
          img: ICON_MAP[cfg.nodeType || "app"],
        },
        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
        name: "node-icon",
      });

      // title text
      group.addShape("text", {
        attrs: {
          textBaseline: "top",
          y: 4,
          x: 24,
          lineHeight: 20,
          text: cfg.title,
          fill: "#fff",
        },
        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
        name: "title",
      });

      group.addShape("marker", {
        attrs: {
          x: 184,
          y: 40,
          r: 6,
          cursor: "pointer",
          symbol: cfg.collapse ? G6.Marker.expand : G6.Marker.collapse,
          stroke: "#666",
          lineWidth: 1,
        },
        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
        name: "collapse-icon",
      });

      group.addShape("text", {
        attrs: {
          textBaseline: "top",
          y: 35,
          x: 24,
          lineHeight: 20,
          text: cfg.des,
          fill: "rgba(0,0,0, 0.4)",
        },
        // must be assigned in G6 3.3 and later versions. it can be any string you want, but should be unique in a custom item type
        name: `index-title-${1}`,
      });
      return shape;
    },
  },
  "single-node"
);

const getTaskList = () => {
  return new Promise((resolve, reject) => {
    resolve(taskFlowView.data);
  });
};
const getTaskRelyList = () => {
  return new Promise((resolve, reject) => {
    resolve(taskRelyList.data);
  });
};

const buildTaskViewer = async () => {
  isLoading.value = true;
  const res: any = await Promise.all([getTaskList(), getTaskRelyList()]);
  isLoading.value = false;
  console.log("resresres", res);
  viewerData.value.nodes.length = 0;
  viewerData.value.edges.length = 0;
  // this.lastLevel = -1
  // this.maxTaskRow = 0
  // this.taskIds.length = 0
  const ids: string[] = [];
  const stages: any = [];
  res[0].forEach((item: any) => {
    let row = 0;
    item.taskList.forEach((task: any) => {
      ids.push(task.id + "");
      // 判断阶段
      if (task.stage?.groupNum) {
        if (
          stages[task.stage.groupNum] &&
          stages[task.stage.groupNum].length > 0
        ) {
          stages[task.stage.groupNum].push(task.id);
        } else {
          stages[task.stage.groupNum] = [task.id];
        }
        task.stage.sortNum = stages[task.stage.groupNum].length;
      }
      viewerData.value.nodes.push({
        id: task.id + "",
        label: task.taskName + "",
        data: { ...task, level: item.level, row },
        layer: item.level > -1 ? item.level : 0,
      });
      row++;
      // if (item.level == 1) {
      //   this.taskIds.push(task.id + '')
      // }
    });
    // this.lastLevel++
    // if (item.taskList.length > this.maxTaskRow) {
    //   this.maxTaskRow = item.taskList.length
    // }
  });

  res[1].forEach((item: any) => {
    if (
      ids.indexOf(item.taskId + "") > -1 &&
      ids.indexOf(item.taskToId + "") > -1
    ) {
      viewerData.value.edges.push({
        id: item.id + "",
        source: item.taskId + "",
        target: item.taskToId + "",
      });
    }
  });

  console.log("viewerData.value", viewerData.value);
  // this.data.nodes.forEach((item: any) => {
  //   console.log(item.data.taskRelyId, 'taskRelyId')
  // })
};

onMounted(() => {
  buildTaskViewer();

  setTimeout(() => {
    const path = "";
    // console.log(G6.Global.version)
    const container: any = document.getElementById("container");
    const width = container.scrollWidth;
    const height = container.scrollHeight || 800;
    graph = new G6.Graph({
      container, // String | HTMLElement，必须，在 Step 1 中创建的容器 id 或容器本身
      width, // Number，必须，图的宽度
      height, // Number，必须，图的高度
      groupByTypes: false,
      enabledStack: true,
      fitCenter: true,
      modes: {
        default: [
          "scroll-canvas",
          "drag-canvas",
          "drag-edge",
          {
            type: "create-edge",
            trigger: "drag",
          },
        ],
      },
      layout: {
        type: "dagre",
        rankdir: "LR",
        // align: 'UL',
        controlPoints: true,
        nodesepFunc: () => 1,
        ranksepFunc: () => 1,
        // type: 'dagre',
        // rankdir: 'LR',
        // controlPoints: true,
        // preventOverlap: true,
        nodeSize: [400, 220],
      },
      defaultNode: {
        size: path.indexOf("template") > -1 ? [298, 129] : [298, 159],
        type: "task-node",
      },
      defaultEdge: {
        type: "task-edge",
        // type: 'polyline',
        // size: 1,
        // color: '#409eff',
        // style: {
        //   endArrow: {
        //     path: 'M 0,0 L 8,4 L 8,-4 Z',
        //     fill: '#409eff'
        //   },
        //   radius: 20
        // }
      },
      // plugins: [minimap, toolbar, tooltip_taskType, tooltip_department, tooltip_executor, tooltip_time, contextMenu]
    });

    graph.data(viewerData.value); // 读取 Step 2 中的数据源到图上
    graph.render(); // 渲染图

    graph.on("node:dblclick", async (ev: any) => {
      const node = ev.item;
      nowTaskId.value = node._cfg.id;

      nextTick(() => {
        taskDetailRef.value.show();
      });
    });

    _processG6.setFlowerNodeHover(graph);

    const setFlowerNodeClick = () => {
      graph.on("node:click", (ev: any) => {
        const node = ev.item;
        const bBox = ev?.target?.cfg?.canvasBBox;
        const model = node.getModel();
        if (ev?.target?.cfg?.name == "add-new-task-btn-yes") {
          console.log("add-new-task-btn-yes click");
          console.log(model, "model");
          fromTask.value = model.data;
          createTaskRef.value.show(); // 显示添加节点对话框
          graph.setItemState(node, "selected", true);
          // const bBox = ev?.target?.cfg?.canvasBBox
          // this._createTaskCtrl.setPosition((bBox?.x + 50) + 'px', (bBox?.y - 28) + 'px')
          // this._createTaskCtrl.setHideFunc(() => {
          //   if (!node) return
          //   graph.setItemState(node, 'create', false)
          //   graph.setItemState(node, 'selected', false)
          //   this.reduceNodeWithEdge(node)
          // })
          // this._createTaskCtrl.setSaveFunc(async (res: taskModel) => {
          //   if (!node) return
          //   graph.setItemState(node, 'create', false)
          //   graph.setItemState(node, 'selected', false)
          //   this.refreshFlow(node)
          // })
          graph.setItemState(node, "create", true);
        } else if (ev?.target?.cfg?.name == "task-del-icon") {
          _msgBoxFun({
            title: "删除",
            con: "是否删除此任务?",
            type: "error",
            confirmButtonText: "删除",
            customClass: "gapFlowMsgBox gapFlowMsgBoxDel",
            roundButton: true,
          }).then(async () => {
            // await this.removeTask(model.id)
            // useTaskStore().clearSubTaskDetail()
            // this.refreshFlow(node)+
            _processG6.isTemplate
              ? await apiRemoveTemplateTask({ ids: model.id })
              : {};
            refreshTaskList();
          });
        } else if (
          ["task-executor-department-icon", "task-department-name"].includes(
            ev?.target?.cfg?.name
          )
        ) {
          // if (!this.isManager) return
          nowTask.value = model?.data;
          console.log("点击部门", nowTask.value);
          if (nowTask.value.status == 3) return;
          // useUpdateTaskStore().getDepartmentList({ projectId: this.projectId, id: this.tableId })
          // updateTaskFloatRef.value.setData(this.isTemplate.value, nodeData.taskTypeId, nodeData.id)
          // updateTaskFloatRef.value.setChooseDepartment(nodeData.organizationId)
          updateTaskFloatRef.value.showDialog(
            "department",
            bBox?.x + "px",
            bBox?.y + 120 + "px"
          );
        } else if (
          ["task-executor-icon", "task-executor-name"].includes(
            ev?.target?.cfg?.name
          )
        ) {
          console.log("执行人");
          // if (!this.isManager) return
          // const nodeData = node.getModel()?.data
          // if (nodeData.status == 3) return
          // this.updateTaskFloatRef.value.setData(this.isTemplate.value, nodeData.taskTypeId, nodeData.id)
          // this.updateTaskFloatRef.value.setChooseDepartment(nodeData.organizationId)
          // this.updateTaskFloatRef.value.setChooseExecutor(nodeData.executor)
          // this.updateTaskFloatRef.value.showDialog('executor', (bBox?.x) + 'px', (bBox?.y + 60) + 'px', this.projectId, this.tableId)
        } else if (
          ["date-time-shape", "date-rect-shape"].includes(ev?.target?.cfg?.name)
        ) {
          // console.log('持续时长')
          // if (!this.isManager) return
          // const nodeData = node.getModel()?.data
          // if (nodeData.status == 3) return
          // this.updateTaskFloatRef.value.setData(this.isTemplate.value, nodeData.taskTypeId, nodeData.id)
          // if (this.isTemplate.value) {
          //   this.updateTaskFloatRef.value.setChooseTaskDay(nodeData.taskDay)
          //   this.updateTaskFloatRef.value.showDialog('time', (bBox?.x) + 'px', (bBox?.y + 60) + 'px')
          // }
          // else if (nodeData.taskType == 2) {
          //   this.updateTaskFloatRef.value.setChooseStartTime(nodeData.startTime)
          //   this.updateTaskFloatRef.value.showDialog('startTime', (bBox?.x + 50) + 'px', (bBox?.y - 28) + 'px')
          // }
        } else if (ev?.target?.cfg?.name == "task-sort") {
          console.log("编辑阶段");
          const nodeData = model?.data;
          openEditStageDialog(nodeData);
        } else {
          const nodes = graph.getNodes();
          const isSelected = node.hasState("selected");
          if (!isSelected) {
            nodes.forEach((no: INode) => {
              no.setState("selected", false);
              _processG6.reduceNodeWithEdge(no, graph);
            });
            node.setState("selected", true);
          } else {
            node.setState("selected", false);
          }
        }
        // const model = node.getModel() as TaskModelConfig
        if (model.data.taskType == 1) {
          _processG6.reduceNodeWithEdge(node, graph);
        }
        // if (this.nowMilestoneId.value ? model.data.milestoneTaskType == 1 : model.data.taskType == 1) {
        //   this.reduceNodeWithEdge(node)
        // }
      });
    };
    setFlowerNodeClick();
  }, 1000);
});

const refreshTaskList = () => {
  buildTaskViewer().then(() => {
    console.log(viewerData.value, "viewerData refreshTaskList");
    graph.data(viewerData.value);
    graph.render();
  });
};
</script>
<!-- 
<style scoped lang="scss">
@boxHeight: 80px; // 盒子高
@boxWidth: 220px; // 盒子宽
@titleHeight: 25px; // 标题高度
@lineColor: #ccc; // 连线颜色
@top-line-height: 30px; // 顶部线高
@bottom-line-height: 90px; // 底部线高

.item {
  width: @boxWidth;
  height: @boxHeight;
  border-radius: 5px;
  border: 1px solid @lineColor;
  box-shadow: 0px 3px 5px @lineColor;
  margin-bottom: @bottom-line-height;
  margin-left: 60px;
  margin-right: 60px;
  position: relative;
  margin-top: 20px;
  &.end-card-wrap {
    margin-top: @bottom-line-height - 10px;
  }
  .flat-line {
    top: -30px;
  }

  .title {
    font-size: 12px;
    height: @titleHeight;
    line-height: 25px;
    background-color: #576a95;
    border-radius: 5px 5px 0 0;
    color: #fff;
    padding-left: 10px;
  }
  .des {
    height: @boxHeight - @titleHeight;
    background-color: white;
    padding: 10px;
    border-radius: 0 0 5px 5px;
  }

  .top-line {
    height: @top-line-height;
    width: 1px;
    background-color: red;
    position: absolute;
    left: 50%;
    top: -@top-line-height;
    z-index: 0;
    position: absolute;
  }

  .bottom-line {
    height: @bottom-line-height;
    width: 1px;
    background-color: @lineColor;
    position: absolute;
    left: 50%;
    z-index: 10;

    &.end-card {
      top: -@bottom-line-height;
    }
    .triangle {
      width: 0;
      height: 0;
      border-left: 5px solid transparent;
      border-right: 5px solid transparent;
      border-top: 5px solid @lineColor;
      position: absolute;
      bottom: 0;
      left: -4px;
    }
    .add-btn {
      width: 80px;
      height: 30px;
      line-height: 30px;
      background-color: white;
      border-radius: 20px;
      box-shadow: 0px 3px 5px @lineColor;
      text-align: center;
      color: #277ace;
      font-size: 12px;
      left: -40px;
      position: absolute;
      bottom: -5px;
      z-index: 10;
      cursor: pointer;
    }
    .add-btn-icon {
      @size: 26px;
      width: @size;
      height: @size;
      line-height: @size - 4;
      border-radius: 50%;
      background-color: #3296fa;
      color: white;
      text-align: center;
      font-size: @size;
      padding: 0;
      position: absolute;
      left: -13px;
      top: 20px;
      cursor: pointer;
    }
  }
}
.wrap-parent,
.wrap-children {
  display: flex;
  justify-content: center;
  // 水平线
  .flat-line {
    height: 1px;
    // width: 110px + 55px;
    width: 100%;
    background-color: @lineColor;
    position: absolute;
    // z-index: 10;

    top: -10px;
    &.right {
      left: 50%;
    }
    &.left {
      right: 50%;
    }
    &.middle {
      left: -65px;
    }
  }
}
.wrap-parent {
  position: relative;
  .next-line {
    height: 1px;
    width: 110px + 55px;
    background-color: @lineColor;
    position: absolute;
    // z-index: 10;
    right: 50%;
    bottom: 0;
    .stand-line {
      position: absolute;
      height: 20px;
      width: 1px;
      background-color: @lineColor;
    }
    &.next-line-2-right {
      left: 50%;
      .stand-line {
        right: 0;
      }
    }
  }
}

.flat-line-bottom {
  width: 110px + 55px;

  background-color: @lineColor;
  height: 1px;
  position: absolute;
  top: -@bottom-line-height;
  &.left {
    left: 50%;
  }
  &.right {
    right: 50%;
  }
}

.layout-start {
  display: flex;
  justify-content: center;
}
.layout-route {
  display: flex;
  justify-content: space-between;
}
</style> -->
